package org.neogenesis.web.loader.arrayExpressLoader;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class ArrayExpressUtils {

	public static final String PLATFORM_EXTENSION = "adf.txt";

	public static final String EXPERIMENT_EXTENSION = "idf";

	public static final String SAMPLE_ARCHIVE_EXTENSION = "processed.1.zip";

	public static final String SAMPLE_EXTENSION = "sdrf";

	/**
	 * dato l'accession name, ritorna la stringa con le righe del file xml
	 * contenente gli url dei file di experiment,platform e samples
	 * 
	 * @param accessionName
	 * @return
	 * @throws IOException
	 * 
	 */
	public static String getFilesByAccession(String accessionName)
			throws IOException {
		URL url = new URL(
				"http://www.ebi.ac.uk/arrayexpress/xml/v2/files?accession="
						+ accessionName);

		HttpURLConnection conn = (HttpURLConnection) url.openConnection();

		if (conn.getResponseCode() != 200) {
			throw new IOException(conn.getResponseMessage());
		}

		try {

			BufferedReader rd = new BufferedReader(new InputStreamReader(
					conn.getInputStream()));
			StringBuilder sb = new StringBuilder();
			String line;
			while ((line = rd.readLine()) != null) {
				sb.append(line);
			}

			rd.close();
			conn.disconnect();

			return sb.toString();

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * @param xml
	 * @return return the url list of the adfs in the file
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 */
	public static List<String> getUrlPlatform(String xml)
			throws ParserConfigurationException, SAXException, IOException {

		List<String> list = new ArrayList<String>();

		StringReader is = new StringReader(xml);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(new InputSource(is));
		doc.getDocumentElement().normalize();

		NodeList nodeList = doc.getElementsByTagName("url");

		for (int i = 0; i < nodeList.getLength(); i++) {

			if (nodeList.item(i).getTextContent().contains(PLATFORM_EXTENSION)) {
				list.add(nodeList.item(i).getTextContent());
			}
		}

		return list;
	}

	/**
	 * @param xml
	 * @return return the url list of the adfs in the file
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 */
	public static String getUrlExperiment(String xml)
			throws ParserConfigurationException, SAXException, IOException {

		StringReader is = new StringReader(xml);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(new InputSource(is));
		doc.getDocumentElement().normalize();

		NodeList nodeList = doc.getElementsByTagName("url");

		for (int i = 0; i < nodeList.getLength(); i++) {

			if (nodeList.item(i).getTextContent()
					.contains(EXPERIMENT_EXTENSION)) {
				return nodeList.item(i).getTextContent();
			}
		}

		return null;
	}

	/**
	 * @param xml
	 * @return return the url of the processed.1.zip (sample archive) in the
	 *         file
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 */
	public static String getUrlSampleArchive(String xml)
			throws ParserConfigurationException, SAXException, IOException {

		StringReader is = new StringReader(xml);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(new InputSource(is));
		doc.getDocumentElement().normalize();

		NodeList nodeList = doc.getElementsByTagName("url");

		for (int i = 0; i < nodeList.getLength(); i++) {

			if (nodeList.item(i).getTextContent().contains(SAMPLE_ARCHIVE_EXTENSION)) {
				return nodeList.item(i).getTextContent();
			}
		}

		return null;
	}

	
	/**
	 * @param xml
	 * @return return the url of the processed.1.zip (sample archive) in the
	 *         file
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 */
	public static String getUrlSampleSdrf(String xml)
			throws ParserConfigurationException, SAXException, IOException {

		StringReader is = new StringReader(xml);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(new InputSource(is));
		doc.getDocumentElement().normalize();

		NodeList nodeList = doc.getElementsByTagName("url");

		for (int i = 0; i < nodeList.getLength(); i++) {

			if (nodeList.item(i).getTextContent().contains(SAMPLE_EXTENSION)) {
				return nodeList.item(i).getTextContent();
			}
		}

		return null;
	}
	
	/**
	 * @param fileUrl
	 * @param savingPath
	 * @return
	 * @throws IOException
	 */
	public static String saveFile(String fileUrl, String savingPath)
			throws IOException {

		URL url = new URL(fileUrl);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		if (conn.getResponseCode() != 200) {
			throw new IOException(conn.getResponseMessage());
		}

		String[] splitUrl = fileUrl.split("/");
		String fileName = splitUrl[splitUrl.length - 1];
		FileOutputStream out = new FileOutputStream(savingPath + fileName);

		byte[] b = new byte[1024];
		int count;
		InputStream in = conn.getInputStream();
		while ((count = in.read(b)) > 0) {
			out.write(b, 0, count);
		}

		out.flush();
		out.close();
		conn.disconnect();
		return fileName;

	}
}
